package model;

import java.util.ArrayList;
import org.jbox2d.collision.shapes.CircleDef;
import org.jbox2d.collision.shapes.PolygonDef;
import org.jbox2d.collision.shapes.ShapeDef;
import org.jbox2d.collision.shapes.ShapeType;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.joints.Joint;
import org.jbox2d.dynamics.joints.RevoluteJoint;
import org.jbox2d.dynamics.joints.RevoluteJointDef;
import controller.Global;

public class Factory {
	static ArrayList<Body> bodyList;

	public static Joint createRevoluteJoint(Body b1, Body b2) {
		RevoluteJointDef jointDef = new RevoluteJointDef();
		jointDef.body1 = b1;
		jointDef.body2 = b2;
		jointDef.localAnchor1 = b1.getWorldCenter();
		jointDef.localAnchor2 = b2.getWorldCenter();
		jointDef.initialize(b1, b2, b1.getWorldCenter());
		return (RevoluteJoint) Global.world.createJoint(jointDef);
	}

	public static Joint createJoint(Joints j) {
		Body b1 = null, b2 = null;
		Joint joint = null;

		for (Body b : bodyList) {
			if (j.entity1.name.equals(((Entity) b.getUserData()).name)) {
				b1 = b;
			}
			if (j.entity2.name.equals(((Entity) b.getUserData()).name)) {
				b2 = b;
			}
		}
		if (b1 != null && b2 != null) {
			joint = createRevoluteJoint(b1, b2);
		}
		return joint;
	}

	public static Body createEntity(Entity o) {
		Body b = null;
		BodyDef definition = new BodyDef();
		Vec2 temp;
		ShapeDef s = null;

		o = o.clone();
		
		if (o != null) {
			if (o.type != Entity.COMPOUND) {
				definition.position.set(o.x, o.y);
				definition.linearDamping = o.linearDamping;
				definition.angularDamping = o.angularDamping;
				definition.fixedRotation = o.fixedRotation;
				
				if (o.type == Entity.CIRCLE) {
					s = new CircleDef();
					s.type = ShapeType.CIRCLE_SHAPE;
					((CircleDef) s).radius = o.radius;
				} else if (o.type == Entity.POLYGON && o.vertices == null) {
					s = new PolygonDef();
					((PolygonDef) s).setAsBox(o.sizeX, o.sizeY);
					s.type = ShapeType.POLYGON_SHAPE;
				} else if (o.type == Entity.POLYGON) {
					s = new PolygonDef();
					for (Vec2 v : o.vertices) {
						temp = new Vec2();
						temp.x = (v.x / o.image.getWidth()) * o.scale;
						temp.y = (v.y / o.image.getHeight()) * o.scale;
						((PolygonDef) s).vertices.add(temp);
					}
					s.type = ShapeType.POLYGON_SHAPE;
				}
				s.isSensor = o.isSensor;
				s.restitution = o.restitution;
				s.density = o.density;
				s.friction = o.friction;

				b = Global.world.createBody(definition);
				o.body = b;
				b.createShape(s);
				b.setUserData(o);
				b.setBullet(o.isBullet);
				b.setMassFromShapes();

				if (!b.isStatic() && !b.isBullet()) {
					Stage.buoyancy.addBody(b);
				}
			} else {
				bodyList = new ArrayList<Body>();
				for (Entity e : o.entityList) {
					bodyList.add(createEntity(e));
				}
				for (Joints j : o.jointList) {
					createJoint(j);
				}
			}
		}
		return b;
	}
}
